/*!
 * \file ClientUapProxy.h
 * \brief Proxy for communication with User Client via UAP protocol
 */

#ifndef SGW_CLIENT_UAP_PROXY_H
#define SGW_CLIENT_UAP_PROXY_H

#include "UserContext.h"
#include <string>
#include "UAP.pb.h"
#include "GAP.pb.h"
#include "RequestHandler.h"
#include "GeneratorEnvironment.h"

namespace tsc
{
namespace sgw
{

class UapGenerator;

/**
 * Proxy for communication with User Client via UAP protocol
 */
class ClientUapProxy
{
public:

	/**
	 * Returns singleton instance of the proxy
	 */
	static ClientUapProxy& instance();

	static void init(common::RequestHandler* rh,
			         common::GeneratorEnvironment& ge);

	/**
	 * Handles received PDU from the external source, i.e User Client.
	 *
	 * \param pMessage - the message contains data to handle which could be for
	 * instance an UapPdu in encoded form
	 */
	void handlePdu(common::Message*& pMessage);

	/**
	 * TODO
	 */
	bool sendUapConnectionCfm(UapGenerator& uapGen);

	/**
	 * TODO
	 */
	bool sendUapConnectionRej(uint32_t                   connectionId,
							  UserApplicationPart::Cause cause);

	/**
	 * TODO
	 */
	bool sendUapMediaBearerSetupCfm(UapGenerator& uapGenerator);

	/**
	 * TODO
	 */
	bool sendUapMediaBearerSetupRej(uint32_t                   connectionId,
	                                UserApplicationPart::Cause cause);

	/**
	 * TODO
	 */
	void handleGapMediaTransmissionFinishedInd(uint32_t connectionId);

	/**
	 * TODO
	 */
	void handleGapMediaBearerSetupCfm(uint32_t connectionId,
	                                  uint32_t serverMediaPort,
	                                  const ProtocolsCommon::IpAddress* serverMediaAddress);

	void handleGapMediaBearerSetupRej(uint32_t connectionId,
	                                  GatewayApplicationPart::Cause cause);

	/**
	 * Adds mapping entry between generatorId(connectionId) and ID of
	 * socket connection which handles this generator
	 */
	void addConnIdMapping(uint32_t generatorId, unsigned int socketConnId);

	void clearConnIdMapping(uint32_t generatorId);

	/**
	 * Finds ID of socket connection handling generator with specified id
	 */
	bool getSocketId(uint32_t generatorId,
	                 unsigned int& socketConnId);

	common::RequestHandler* getRequestHandler();

private:
	/**
     * Handle UapPdu received from UserClient
     *
     * \param uapPdu the pdu to handle
     * \param ID of socket connection on which the pdu arrived
     */
    void handleUapPdu(UserApplicationPart::UapPdu*& uapPdu,
                      unsigned int socketConnId);


    /**
     * Sends the provided encoded UAP message over UapSocket to the User Client
     *
     * \param connectionId ID of the connection
     * \param msg encoded UAP message to send
     * \param pduNum UapPduNumber of the message to send
     * \return <code>true</code> on success, <code>false</code> otherwise
     */
    bool sendUapPdu(uint32_t                          connectionId,
                    const std::string&                msg,
                    UserApplicationPart::UapPduNumber pduNum);

	ClientUapProxy(common::RequestHandler* rh,
			       common::GeneratorEnvironment& ge);

	~ClientUapProxy();

	common::RequestHandler* mpReqHandler;
	common::GeneratorEnvironment& _ge;

	static ClientUapProxy* mInstance;

	// key=> generatorId, value=> socketConnId
	std::map<uint32_t, unsigned int> mSocketIdtoGenIdMap;
};

} // namespace sgw
} // namespace tsc

#endif // SGW_CLIENT_UAP_PROXY_H
